| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | 1× 1× 1× 1× 1× | // // // // // // // // // // import Vue from 'vue' import Drag from '../utils/drag' import translateUtil from '../utils/translate' import * as domUtil from '../utils/domUtil' const ITEM_HEIGHT = 36 export default { props: { divider: { type: Boolean, default: false }, content: { type: String, default: '' }, values: { type: Array, default () { return [] } }, value: {}, textAlign: { type: String, default: '' }, width: { type: String, default: '' }, visibleItemCount: { type: Number, default: 5 } }, data () { return { animate: false } }, computed: { contentHeight () { return ITEM_HEIGHT * this.visibleItemCount }, valueIndex () { return this.values.indexOf(this.value) }, dragRange () { let values = this.values let visibleItemCount = this.visibleItemCount return [ -ITEM_HEIGHT * (values.length - Math.ceil(visibleItemCount / 2)), ITEM_HEIGHT * Math.floor(visibleItemCount / 2) ] } }, mounted: function () { if (!this.divider) { this.initEvents() this.doOnValueChange() } }, methods: { value2Translate (value) { let values = this.values let valueIndex = values.indexOf(value) let offset = Math.floor(this.visibleItemCount / 2) if (valueIndex !== -1) { return (valueIndex - offset) * -ITEM_HEIGHT } }, translate2Value (translate) { translate = Math.round(translate / ITEM_HEIGHT) * ITEM_HEIGHT let index = -(translate - Math.floor(this.visibleItemCount / 2) * ITEM_HEIGHT) / ITEM_HEIGHT return this.values[index] }, doOnValueChange () { let value = this.value let wrapper = this.$refs.wrapper translateUtil.translateElement(wrapper, null, this.value2Translate(value)) }, doOnValuesChange () { let el = this.$el let items = el.querySelectorAll('.mu-picker-item') Array.prototype.forEach.call(items, (item, index) => { translateUtil.translateElement(item, null, ITEM_HEIGHT * index) }) }, initEvents () { let el = this.$refs.wrapper let drag = new Drag(el) let startTop = 0 let velocityTranslate, prevTranslate drag.start(() => { startTop = translateUtil.getElementTranslate(el).top }).drag((endPos, event) => { event.preventDefault() event.stopPropagation() let translate = startTop + endPos.y translateUtil.translateElement(el, 0, translate) velocityTranslate = translate - prevTranslate || translate prevTranslate = translate }).end((endPos) => { const momentumRatio = 7 let currentTranslate = translateUtil.getElementTranslate(el).top let momentumTranslate if (endPos.time < 300) { momentumTranslate = currentTranslate + velocityTranslate * momentumRatio } let dragRange = this.dragRange this.animate = true domUtil.transitionEnd(el, () => { this.animate = false }) Vue.nextTick(() => { let translate if (momentumTranslate) { translate = Math.round(momentumTranslate / ITEM_HEIGHT) * ITEM_HEIGHT } else { translate = Math.round(currentTranslate / ITEM_HEIGHT) * ITEM_HEIGHT } translate = Math.max(Math.min(translate, dragRange[1]), dragRange[0]) translateUtil.translateElement(el, null, translate) this.$emit('change', this.translate2Value(translate)) }) }) } }, watch: { values (newVal) { if (this.valueIndex === -1) { this.value = (newVal || [])[0] } }, value () { this.doOnValueChange() } } } |